use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};
use std::io::Write;
use tauri::{command, AppHandle};
use dirs;
use calamine::{open_workbook, Reader, Xlsx, DataType};
use chrono::Local;
use log::{error, info, warn};

// 嵌入模板文件
const TEMPLATE_DOCX: &[u8] = include_bytes!("../../template.docx");

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SubProcess {
    pub description: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FunctionProcess {
    pub name: String,
    pub sub_processes: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FunctionRequirement {
    pub name: String,
    pub processes: Vec<FunctionProcess>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct OverviewDesignRequest {
    pub cosmic_file_path: String,
    pub requirement_name: String,
    pub author: String,
    pub writing_time: String,
    pub output_path: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct OverviewDesignResponse {
    pub success: bool,
    pub message: String,
    pub output_path: Option<String>,
}

/// 从COSMIC Excel文件中提取结构化数据
fn extract_structured_feature_data(file_path: &str) -> Result<Vec<FunctionRequirement>, String> {
    info!("开始从Excel文件提取数据: {}", file_path);
    
    if !Path::new(file_path).exists() {
        error!("文件不存在: {}", file_path);
        return Err(format!("文件不存在: {}", file_path));
    }

    info!("正在打开Excel文件...");
    let mut workbook: Xlsx<_> = open_workbook(file_path)
        .map_err(|e| {
            error!("无法打开Excel文件: {}", e);
            format!("无法打开Excel文件: {}", e)
        })?;

    // 查找包含"功能点拆分表"的工作表
    info!("查找包含'功能点拆分表'的工作表...");
    let sheet_names = workbook.sheet_names();
    info!("可用的工作表: {:?}", sheet_names);
    
    let target_sheet_name = sheet_names
        .iter()
        .find(|name| name.contains("功能点拆分表"))
        .ok_or_else(|| {
            error!("未找到包含'功能点拆分表'的工作表");
            "未找到包含'功能点拆分表'的工作表".to_string()
        })?
        .clone();

    info!("找到目标工作表: {}", target_sheet_name);

    let range = workbook
        .worksheet_range(&target_sheet_name)
        .map_err(|e| format!("无法读取工作表: {}", e))?;

    let mut structured_data = Vec::new();
    let mut current_requirement: Option<FunctionRequirement> = None;
    let mut current_process: Option<FunctionProcess> = None;
    let mut last_c_value: Option<String> = None;
    let mut last_e_value: Option<String> = None;

    // 从第4行开始读取数据（索引从0开始，所以是第3行）
    for row_idx in 3..range.height() {
        // 读取C列（功能用户需求）、E列（功能过程）、F列（子过程描述）
        let c_value = range.get_value((row_idx as u32, 2)).and_then(|v| v.as_string()).map(|s| s.trim().to_string());
        let e_value = range.get_value((row_idx as u32, 4)).and_then(|v| v.as_string()).map(|s| s.trim().to_string());
        let f_value = range.get_value((row_idx as u32, 5)).and_then(|v| v.as_string()).map(|s| s.trim().to_string());

        // 确定当前行的有效值（处理合并单元格）
        let current_c = c_value.or_else(|| last_c_value.clone());
        let current_e = e_value.or_else(|| last_e_value.clone());
        let current_f = f_value;

        // 如果F列为空，跳过这一行
        let should_add_subprocess = current_f.as_ref().map_or(false, |f| !f.is_empty());

        // 检查功能用户需求是否变化
        if let Some(ref c) = current_c {
            if last_c_value.as_ref() != Some(c) {
                // 保存之前的需求
                if let Some(req) = current_requirement.take() {
                    structured_data.push(req);
                }
                
                // 创建新的需求
                current_requirement = Some(FunctionRequirement {
                    name: c.clone(),
                    processes: Vec::new(),
                });
                last_c_value = Some(c.clone());
                current_process = None;
                last_e_value = None;
            }
        }

        // 检查功能过程是否变化
        if let Some(ref e) = current_e {
            if last_e_value.as_ref() != Some(e) {
                if let Some(ref mut req) = current_requirement {
                    // 保存之前的过程
                    if let Some(proc) = current_process.take() {
                        req.processes.push(proc);
                    }
                    
                    // 创建新的过程
                    current_process = Some(FunctionProcess {
                        name: e.clone(),
                        sub_processes: Vec::new(),
                    });
                    last_e_value = Some(e.clone());
                } else {
                    warn!("在行 {} 发现功能过程 '{}' 但缺少有效的上级功能需求", row_idx + 1, e);
                    continue;
                }
            }
        }

        // 添加子过程描述
        if should_add_subprocess {
            if let (Some(ref mut proc), Some(f)) = (current_process.as_mut(), current_f.as_ref()) {
                proc.sub_processes.push(f.clone());
            } else if current_requirement.is_some() {
                warn!("在行 {} 发现子过程 '{}' 但缺少有效的功能过程归属", row_idx + 1, current_f.as_ref().unwrap_or(&String::new()));
            }
        }
    }

    // 保存最后的数据
    if let Some(proc) = current_process {
        if let Some(ref mut req) = current_requirement {
            req.processes.push(proc);
        }
    }
    if let Some(req) = current_requirement {
        structured_data.push(req);
    }

    info!("成功提取到 {} 个功能需求", structured_data.len());
    Ok(structured_data)
}

/// 替换Word文档中的占位符
fn replace_placeholders_in_docx(
    template_path: &str,
    output_path: &str,
    replacements: &HashMap<String, String>,
    structured_data: &[FunctionRequirement],
) -> Result<(), String> {
    info!("开始处理Word文档模板: {}", template_path);

    // 先简单复制模板文件到输出路径
    fs::copy(template_path, output_path)
        .map_err(|e| format!("无法复制模板文件: {}", e))?;

    // 读取模板文件
    let template_bytes = fs::read(template_path)
        .map_err(|e| format!("无法读取模板文件: {}", e))?;

    // 使用zip库处理docx文件（docx本质上是zip文件）
    let cursor = std::io::Cursor::new(template_bytes);
    let mut archive = zip::ZipArchive::new(cursor)
        .map_err(|e| format!("无法解析docx文件: {}", e))?;

    let mut new_archive_data = Vec::new();
    {
        let cursor = std::io::Cursor::new(&mut new_archive_data);
        let mut new_archive = zip::ZipWriter::new(cursor);

        for i in 0..archive.len() {
            let mut file = archive.by_index(i)
                .map_err(|e| format!("无法读取zip条目: {}", e))?;
            
            let file_name = file.name().to_string();
            let mut content = Vec::new();
            std::io::copy(&mut file, &mut content)
                .map_err(|e| format!("无法读取文件内容: {}", e))?;

            // 如果是document.xml文件，进行文本替换
            if file_name == "word/document.xml" {
                let mut xml_content = String::from_utf8(content)
                    .map_err(|e| format!("无法解析XML内容: {}", e))?;

                // 执行基本占位符替换
                for (placeholder, value) in replacements {
                    xml_content = xml_content.replace(placeholder, value);
                }

                // 处理结构化数据插入
                xml_content = insert_structured_data_to_xml(xml_content, structured_data)?;

                content = xml_content.into_bytes();
            }

            // 写入新的zip文件
            new_archive.start_file::<_, ()>(file_name, zip::write::FileOptions::default())
                .map_err(|e| format!("无法创建zip条目: {}", e))?;
            new_archive.write_all(&content)
                .map_err(|e| format!("无法写入zip条目: {}", e))?;
        }

        new_archive.finish()
            .map_err(|e| format!("无法完成zip文件创建: {}", e))?;
    }

    // 写入输出文件
    fs::write(output_path, new_archive_data)
        .map_err(|e| format!("无法写入输出文件: {}", e))?;

    info!("成功生成概要设计文档: {}", output_path);
    Ok(())
}

/// 在XML中插入结构化数据
fn insert_structured_data_to_xml(
    mut xml_content: String,
    structured_data: &[FunctionRequirement],
) -> Result<String, String> {
    // 查找功能需求部分的占位符
    if let Some(placeholder_pos) = xml_content.find("${functional_requirements_section}") {
        let mut requirements_xml = String::new();
        
        for req_data in structured_data {
            // 添加需求标题
            requirements_xml.push_str(&format!(
                r#"<w:p><w:pPr><w:pStyle w:val="Heading3"/></w:pPr><w:r><w:t>{}</w:t></w:r></w:p>"#,
                escape_xml(&req_data.name)
            ));

            // 添加功能过程列表
            for (i, process) in req_data.processes.iter().enumerate() {
                requirements_xml.push_str(&format!(
                    r#"<w:p><w:pPr><w:numPr><w:ilvl w:val="0"/><w:numId w:val="1"/></w:numPr></w:pPr><w:r><w:t>{}. {}</w:t></w:r></w:p>"#,
                    i + 1,
                    escape_xml(&process.name)
                ));

                // 添加子过程
                for sub_process in &process.sub_processes {
                    requirements_xml.push_str(&format!(
                        r#"<w:p><w:pPr><w:numPr><w:ilvl w:val="1"/><w:numId w:val="1"/></w:numPr></w:pPr><w:r><w:t>{}</w:t></w:r></w:p>"#,
                        escape_xml(sub_process)
                    ));
                }
            }
        }

        xml_content.replace_range(
            placeholder_pos..placeholder_pos + "${functional_requirements_section}".len(),
            &requirements_xml,
        );
    }

    // 处理表格占位符
    if let Some(table_pos) = xml_content.find("${table}") {
        let table_xml = generate_table_xml(structured_data)?;
        xml_content.replace_range(
            table_pos..table_pos + "${table}".len(),
            &table_xml,
        );
    }

    Ok(xml_content)
}

/// 生成表格XML
fn generate_table_xml(structured_data: &[FunctionRequirement]) -> Result<String, String> {
    let mut table_xml = String::new();
    
    // 表格开始
    table_xml.push_str(r#"<w:tbl><w:tblPr><w:tblStyle w:val="TableGrid"/><w:tblW w:w="0" w:type="auto"/></w:tblPr>"#);
    
    // 表头
    table_xml.push_str(r#"<w:tr><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="FFFF00"/></w:tcPr><w:p><w:r><w:t>一级需求</w:t></w:r></w:p></w:tc>"#);
    table_xml.push_str(r#"<w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="FFFF00"/></w:tcPr><w:p><w:r><w:t>二级需求</w:t></w:r></w:p></w:tc>"#);
    table_xml.push_str(r#"<w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="FFFF00"/></w:tcPr><w:p><w:r><w:t>三级需求</w:t></w:r></w:p></w:tc></w:tr>"#);

    // 表格数据
    for req_data in structured_data {
        for process in &req_data.processes {
            table_xml.push_str(&format!(
                r#"<w:tr><w:tc><w:p><w:r><w:t>{}</w:t></w:r></w:p></w:tc><w:tc><w:p><w:r><w:t>{}</w:t></w:r></w:p></w:tc><w:tc><w:p><w:r><w:t>{}</w:t></w:r></w:p></w:tc></w:tr>"#,
                escape_xml(&req_data.name),
                escape_xml(&req_data.name),
                escape_xml(&process.name)
            ));
        }
    }

    // 表格结束
    table_xml.push_str("</w:tbl>");
    
    Ok(table_xml)
}

/// XML转义
fn escape_xml(text: &str) -> String {
    text.replace('&', "&amp;")
        .replace('<', "&lt;")
        .replace('>', "&gt;")
        .replace('"', "&quot;")
        .replace('\'', "&apos;")
}

#[command]
pub async fn generate_overview_design(_app_handle: AppHandle, request: OverviewDesignRequest) -> Result<OverviewDesignResponse, String> {
    info!("=== 开始生成概要设计文档 ===");
    info!("请求参数: {:?}", request);

    // 验证输入参数
    info!("验证输入参数...");
    if request.cosmic_file_path.is_empty() {
        error!("COSMIC文件路径为空");
        return Ok(OverviewDesignResponse {
            success: false,
            message: "COSMIC文件路径不能为空".to_string(),
            output_path: None,
        });
    }
    info!("COSMIC文件路径: {}", request.cosmic_file_path);

    if request.requirement_name.is_empty() {
        error!("需求名称为空");
        return Ok(OverviewDesignResponse {
            success: false,
            message: "需求名称不能为空".to_string(),
            output_path: None,
        });
    }
    info!("需求名称: {}", request.requirement_name);
    info!("作者: {}", request.author);
    info!("编写时间: {}", request.writing_time);

    // 检查COSMIC文件是否存在
    info!("检查COSMIC文件是否存在: {}", request.cosmic_file_path);
    if !Path::new(&request.cosmic_file_path).exists() {
        error!("COSMIC文件不存在: {}", request.cosmic_file_path);
        return Ok(OverviewDesignResponse {
            success: false,
            message: format!("COSMIC文件不存在: {}", request.cosmic_file_path),
            output_path: None,
        });
    }
    info!("COSMIC文件存在，继续处理");

    // 创建临时模板文件（优先使用嵌入数据）
    let temp_template_path = {
        // 创建临时目录
        let temp_dir = std::env::temp_dir();
        let temp_template = temp_dir.join("temp_template.docx");
        
        // 首先尝试使用嵌入的模板数据
        match std::fs::write(&temp_template, TEMPLATE_DOCX) {
            Ok(_) => {
                info!("成功使用嵌入的模板数据创建临时文件: {}", temp_template.display());
                temp_template
            }
            Err(e) => {
                warn!("使用嵌入模板数据失败: {}，尝试文件系统路径", e);
                
                // 回退到文件系统路径
                let dev_path = Path::new("src-tauri/template.docx");
                if dev_path.exists() {
                    dev_path.to_path_buf()
                } else {
                    // 如果开发环境路径不存在，尝试相对于可执行文件的路径
                    let exe_dir = std::env::current_exe()
                        .map_err(|e| format!("无法获取可执行文件路径: {}", e))?
                        .parent()
                        .ok_or("无法获取可执行文件目录")?
                        .to_path_buf();
                    let resource_path = exe_dir.join("template.docx");
                    if resource_path.exists() {
                        resource_path
                    } else {
                        error!("模板文件不存在，既不在嵌入数据中，也不在文件系统中");
                        return Ok(OverviewDesignResponse {
                            success: false,
                            message: "模板文件不存在".to_string(),
                            output_path: None,
                        });
                    }
                }
            }
        }
    };
    
    let template_path_str = temp_template_path.to_string_lossy();
    info!("使用模板文件: {}", template_path_str);

    // 提取COSMIC数据
    info!("开始提取COSMIC数据...");
    let structured_data = match extract_structured_feature_data(&request.cosmic_file_path) {
        Ok(data) => {
            info!("成功提取COSMIC数据，共 {} 个功能需求", data.len());
            for (i, req) in data.iter().enumerate() {
                info!("功能需求 {}: {}, 包含 {} 个功能过程", i + 1, req.name, req.processes.len());
            }
            data
        },
        Err(e) => {
            error!("提取COSMIC数据失败: {}", e);
            return Ok(OverviewDesignResponse {
                success: false,
                message: format!("提取COSMIC数据失败: {}", e),
                output_path: None,
            });
        }
    };

    // 准备替换内容
    info!("准备文档替换内容...");
    let mut replacements = HashMap::new();
    replacements.insert("${name}".to_string(), request.requirement_name.clone());
    replacements.insert("${author}".to_string(), request.author);
    replacements.insert("${date}".to_string(), request.writing_time);
    replacements.insert("${content}".to_string(), "".to_string());
    replacements.insert("${test_info}".to_string(), "".to_string());
    info!("替换内容准备完成: {:?}", replacements);

    // 生成输出文件路径
    let output_path = if request.output_path.is_empty() {
        let timestamp = Local::now().format("%Y%m%d_%H%M%S");
        let filename = format!("{}@概要设计说明书_{}.docx", request.requirement_name, timestamp);
        
        // 使用与COSMIC文件相同的存储逻辑 - 优先使用用户目录
        let path = if let Some(download_dir) = dirs::download_dir() {
            download_dir.join(&filename)
        } else if let Some(document_dir) = dirs::document_dir() {
            document_dir.join(&filename)
        } else if let Some(desktop_dir) = dirs::desktop_dir() {
            desktop_dir.join(&filename)
        } else {
            // 最后的备选方案：使用当前用户的主目录
            dirs::home_dir()
                .unwrap_or_else(|| std::path::PathBuf::from("."))
                .join(&filename)
        };
        path.to_string_lossy().to_string()
    } else {
        // 如果用户提供了路径，确保它是绝对路径
        let path = Path::new(&request.output_path);
        if path.is_absolute() {
            request.output_path
        } else {
            // 相对路径也基于用户目录而不是项目目录
            let base_dir = dirs::download_dir()
                .or_else(|| dirs::document_dir())
                .or_else(|| dirs::desktop_dir())
                .or_else(|| dirs::home_dir())
                .unwrap_or_else(|| std::path::PathBuf::from("."));
            let absolute_path = base_dir.join(&request.output_path);
            absolute_path.to_string_lossy().to_string()
        }
    };
    info!("输出文件路径: {}", output_path);

    // 生成文档
    info!("开始生成文档...");
    match replace_placeholders_in_docx(&template_path_str, &output_path, &replacements, &structured_data) {
        Ok(_) => {
            info!("概要设计文档生成成功: {}", output_path);
            info!("=== 概要设计文档生成完成 ===");
            Ok(OverviewDesignResponse {
                success: true,
                message: "概要设计文档生成成功".to_string(),
                output_path: Some(output_path),
            })
        }
        Err(e) => {
            error!("生成概要设计文档失败: {}", e);
            error!("=== 概要设计文档生成失败 ===");
            Ok(OverviewDesignResponse {
                success: false,
                message: format!("生成文档失败: {}", e),
                output_path: None,
            })
        }
    }
}